package cn.stylefeng.guns.modular.business.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.stylefeng.guns.modular.business.comment.YunHeKey;
import cn.stylefeng.guns.modular.business.entity.SubClassInfo;
import cn.stylefeng.guns.modular.business.entity.SubFileInfo;
import cn.stylefeng.guns.modular.business.enums.SubClassInfoExceptionEnum;
import cn.stylefeng.guns.modular.business.enums.SubDrawInfoExceptionEnum;
import cn.stylefeng.guns.modular.business.mapper.SubClassInfoMapper;
import cn.stylefeng.guns.modular.business.pojo.SubClassInfoRequest;
import cn.stylefeng.guns.modular.business.pojo.SubFileInfoRequest;
import cn.stylefeng.guns.modular.business.service.SubClassInfoService;
import cn.stylefeng.guns.modular.business.service.SubFileInfoService;
import cn.stylefeng.guns.modular.business.service.SubUseBrowseService;
import cn.stylefeng.roses.kernel.auth.api.LoginUserApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 课程数据业务实现层
 *
 * @author zhangyaowen
 * @date 2021/08/18 14:09
 */
@Service
public class SubClassInfoServiceImpl extends ServiceImpl<SubClassInfoMapper, SubClassInfo> implements SubClassInfoService {

    @Resource
    private SubFileInfoService subFileInfoService;
    @Resource
    private LoginUserApi loginUserApi;
    @Resource
    private SubUseBrowseService subUseBrowseService;

	@Override
    public void add(SubClassInfoRequest subClassInfoRequest) {
        SubClassInfo subClassInfo = new SubClassInfo();
        BeanUtil.copyProperties(subClassInfoRequest, subClassInfo);
        this.save(subClassInfo);
    }

    @Override
    public void del(SubClassInfoRequest subClassInfoRequest) {
        SubClassInfo subClassInfo = this.querySubClassInfo(subClassInfoRequest);
        this.removeById(subClassInfo.getId());
    }

    @Override
    public void edit(SubClassInfoRequest subClassInfoRequest) {
        SubClassInfo subClassInfo = this.querySubClassInfo(subClassInfoRequest);
        BeanUtil.copyProperties(subClassInfoRequest, subClassInfo);
        this.updateById(subClassInfo);
    }

    @Override
    public SubClassInfo detail(SubClassInfoRequest subClassInfoRequest) {
        return this.querySubClassInfo(subClassInfoRequest);
    }

    @Override
    public PageResult<Map<String, Object>> findPage(SubClassInfoRequest subClassInfoRequest) {
        LambdaQueryWrapper<SubClassInfo> queryWrapper = new LambdaQueryWrapper<>();

        String className = subClassInfoRequest.getClassName();

        queryWrapper.like(ObjectUtil.isNotEmpty(className), SubClassInfo::getClassName, className);

        List<SubClassInfo> sysRolePage = this.list(queryWrapper);

//        PageResult<SubClassInfo> subClassInfoPageResult= PageResultFactory.createPageResult(sysRolePage);
//        List<SubClassInfo> list = subClassInfoPageResult.getRows();
        PageResult<Map<String, Object>> pageResult = new PageResult<>();
        List<Map<String,Object>> mapList = new ArrayList<>();
        for(SubClassInfo subClassInfo : sysRolePage){

            Map<String, Object> map = new HashMap<String, Object>();
            //map = JSONObject.parseObject(JSONObject.toJSONString(subClassInfo), Map.class);
            //map.remove("id");
//            byte[] key = YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
//            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
//
//            String jmid = YunHeKey.YUNHEKC+subClassInfo.getClassName();
//            String encryptHex = aes.encryptHex(jmid);
//            map.put("id",encryptHex);
            SubFileInfoRequest subFileInfoRequest = new SubFileInfoRequest();
            subFileInfoRequest.setFileType(1L);
            subFileInfoRequest.setFileOriginName(subClassInfo.getClassName());
            subFileInfoRequest.setFileFirstBelong(YunHeKey.KECHENG);
            List<SubFileInfo> subFileInfoPageResult = subFileInfoService.findIndexId(subFileInfoRequest);
            if(!subFileInfoPageResult.isEmpty()) {
                map.put("fileId", subFileInfoPageResult.get(0).getId());
            }

            map.put("className",subClassInfo.getClassName());
            map.put("classIntroduction",subClassInfo.getClassIntroduction());
            //map去重
//        Map<String, Object> sortMap = new LinkedHashMap<>();
//        map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(e -> sortMap.put(e.getKey(), e.getValue()));
            mapList.add(map);
        }
        //List<map>去重 生成新的list
        ArrayList<Map<String, Object>> cs = mapList.stream()
                .collect(Collectors
                        .collectingAndThen(Collectors
                                .toCollection(() -> new TreeSet<>(new Comparator<Map<String, Object>>() {
                                    @Override    //重写比较器
                                    public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                                        if (o1.get("className").equals(o2.get("className"))) {
                                            return 0;
                                        }
                                        return 1;
                                    }

                                })), ArrayList::new));

//        pageResult.setRows(cs);
//        pageResult.setPageNo(subClassInfoPageResult.getPageNo());
//        if(cs.size()<subClassInfoPageResult.getPageSize()){
//            pageResult.setTotalPage(1);
//        }else{
//            pageResult.setTotalPage((int)cs.size()/subClassInfoPageResult.getPageSize());
//        }
//        pageResult.setPageSize(subClassInfoPageResult.getPageSize());
//        pageResult.setTotalRows(cs.size());

        Page<Map<String, Object>> page = PageFactory.defaultPage();
        Page<Map<String, Object>> pages = new Page<>(page.getCurrent(),page.getSize());
        int start =(int)((page.getCurrent()-1)*page.getSize());
        int end =(int)((page.getCurrent())*page.getSize());
        if(cs.size()<end){
            end = cs.size();
        }
        List<Map<String, Object>> t2 = cs.subList(start,end);
        pages.setRecords(t2);
        pages.setTotal(cs.size());
        PageResult<Map<String, Object>> pageResults =  PageResultFactory.createPageResult(pages);

        pageResult.setRows(t2);
        pageResult.setPageNo(Integer.parseInt(pages.getCurrent()+""));
        pageResult.setPageSize(Integer.parseInt(pages.getSize()+""));
        if(cs.size()<pageResult.getPageSize()){
            pageResult.setTotalPage(1);
        }else{
            pageResult.setTotalPage((int)cs.size()/pageResult.getPageSize());
        }

        pageResult.setTotalRows(cs.size());

        return pageResult;
    }

    @Override
    public List<Map<String,Object>> findList(SubClassInfoRequest subClassInfoRequest) {
        LambdaQueryWrapper<SubClassInfo> queryWrapper = new LambdaQueryWrapper<>();

        String className = subClassInfoRequest.getClassName();

        queryWrapper.eq(ObjectUtil.isNotEmpty(className), SubClassInfo::getClassName, className);
        List<Map<String,Object>> mapList = new ArrayList<>();
        List<SubClassInfo> list= this.list(queryWrapper);
        for(SubClassInfo subClassInfo : list){

            Map<String, Object> map = new HashMap<String, Object>();
            //map = JSONObject.parseObject(JSONObject.toJSONString(subClassInfo), Map.class);
            //map.remove("id");
            byte[] key = YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);

            String jmid = YunHeKey.YHKC+subClassInfo.getId();
            String encryptHex = aes.encryptHex(jmid);
            map.put("id",encryptHex);
            SubFileInfoRequest subFileInfoRequest = new SubFileInfoRequest();
            subFileInfoRequest.setFileType(1L);
            subFileInfoRequest.setFileOriginName(subClassInfo.getClassName());
            subFileInfoRequest.setFileFirstBelong(YunHeKey.KECHENG);
            List<SubFileInfo> subFileInfoPageResult = subFileInfoService.findIndexId(subFileInfoRequest);
            if(!subFileInfoPageResult.isEmpty()) {
                map.put("fileId", subFileInfoPageResult.get(0).getId());
                map.put("fileType", subFileInfoPageResult.get(0).getFileType());
            }

            map.put("classListname",subClassInfo.getClassListname());
            //map去重
//        Map<String, Object> sortMap = new LinkedHashMap<>();
//        map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(e -> sortMap.put(e.getKey(), e.getValue()));
            mapList.add(map);
        }
        return mapList;
    }

    /**
     * 获取信息
     *
     * @author zhangyaowen
     * @date 2021/08/18 14:09
     */
    private SubClassInfo querySubClassInfo(SubClassInfoRequest subClassInfoRequest) {
        SubClassInfo subClassInfo = this.getById(subClassInfoRequest.getId());
        if (ObjectUtil.isEmpty(subClassInfo)) {
            throw new ServiceException(SubClassInfoExceptionEnum.SUBCLASSINFO_NOT_EXISTED);
        }
        return subClassInfo;
    }

    /**
     * 创建查询wrapper
     *
     * @author zhangyaowen
     * @date 2021/08/18 14:09
     */
    private LambdaQueryWrapper<SubClassInfo> createWrapper(SubClassInfoRequest subClassInfoRequest) {
        LambdaQueryWrapper<SubClassInfo> queryWrapper = new LambdaQueryWrapper<>();

        Long id = subClassInfoRequest.getId();
        String className = subClassInfoRequest.getClassName();
        String classIntroduction = subClassInfoRequest.getClassIntroduction();
        String classSpeaker = subClassInfoRequest.getClassSpeaker();
        String speakerIntroduction = subClassInfoRequest.getSpeakerIntroduction();
        String classFrom = subClassInfoRequest.getClassFrom();
        String classTime = subClassInfoRequest.getClassTime();
        String classListname = subClassInfoRequest.getClassListname();

        queryWrapper.eq(ObjectUtil.isNotNull(id), SubClassInfo::getId, id);
        queryWrapper.like(ObjectUtil.isNotEmpty(className), SubClassInfo::getClassName, className);
        queryWrapper.like(ObjectUtil.isNotEmpty(classIntroduction), SubClassInfo::getClassIntroduction, classIntroduction);
        queryWrapper.like(ObjectUtil.isNotEmpty(classSpeaker), SubClassInfo::getClassSpeaker, classSpeaker);
        queryWrapper.like(ObjectUtil.isNotEmpty(speakerIntroduction), SubClassInfo::getSpeakerIntroduction, speakerIntroduction);
        queryWrapper.like(ObjectUtil.isNotEmpty(classFrom), SubClassInfo::getClassFrom, classFrom);
        queryWrapper.like(ObjectUtil.isNotEmpty(classTime), SubClassInfo::getClassTime, classTime);
        queryWrapper.like(ObjectUtil.isNotEmpty(classListname), SubClassInfo::getClassListname, classListname);

        return queryWrapper;
    }

    @Override
    public List<Map<String, Object>> toReview(String  id) {
        byte[] key = YunHeKey.PASSWORD.getBytes(StandardCharsets.UTF_8);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        String decryptStr = aes.decryptStr(id, CharsetUtil.CHARSET_UTF_8);
        //获取ID字符串YD后面真实的的id
        String jmid = StrUtil.subAfter(decryptStr,YunHeKey.YHKC,false);
        HttpServletRequest request = HttpServletUtil.getRequest();
        Long userid ;
        if (ObjectUtil.isNotNull(request)) {

//            //获取token
//            String token = authService.getTokenFromRequest(request);
//
//            //如果token为空直接返回
//            if (ObjectUtil.isEmpty(token)) {
//                //匿名用户
//                userid = -1l;
//            }else {
//                //校验token，错误则抛异常，待确定
//                authService.checkToken(token);
//
//                //根据token获取JwtPayLoad部分
//                JwtPayLoad jwtPayLoad = JwtTokenUtil.getJwtPayLoad(token);
//                if (jwtPayLoad != null) {
//                    //获取缓存的key
//                    String loginUserCacheKey = jwtPayLoad.getUuid();
//                    userid = jwtPayLoad.getUserId();
//                } else {
//                    userid = 0l;
//                }
//            }
            LoginUser loginUser = loginUserApi.getLoginUser();
            userid = loginUser.getUserId();
        } else {
            throw new ServiceException(SubDrawInfoExceptionEnum.REQUEST_EMPTY);
        }
        LambdaQueryWrapper<SubClassInfo> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(ObjectUtil.isNotEmpty(jmid), SubClassInfo::getId, jmid);
        List<SubClassInfo> subClassInfoList = this.list(queryWrapper);
        if(userid != 0l && userid != -1l) {
            subUseBrowseService.saveBrowse(YunHeKey.KECHENG,subClassInfoList.get(0).getClassName(),userid,request);
        }
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (SubClassInfo subClassInfo : subClassInfoList) {

            Map<String, Object> map = new HashMap<String, Object>();
            map = JSONObject.parseObject(JSONObject.toJSONString(subClassInfo), Map.class);

            // 获取类的属性
            Field[] declaredFields = SubClassInfo.class.getDeclaredFields();
            List<Map<String, Object>> mplist = new ArrayList<>();
            // 遍历属性，获取属性上ApiModelProperty的值，属性的名，存入Properties
            if (declaredFields.length != 0) {

                int i = 1;
                Map<String, Object> p = new HashMap<String, Object>();
                for (Field field : declaredFields) {

                    Map<String, Object> mp = new HashMap<String, Object>();
                    if (field.getAnnotation(ApiModelProperty.class) != null) {
                        //获取注解属性
                        ApiModelProperty aa = field.getAnnotation(ApiModelProperty.class);
                        // key和value可根据需求存
                        // 这存的key为注解的值，value为类属性名
//                        if (!"bookName".equals(field.getName())) {


                        if ("className".equals(field.getName()) ) {
                            p.put(field.getName(), map.get(field.getName()));

                        }
                        else {
                            mp.put("key", aa.value());
                            mp.put("value", map.get(field.getName()));

                            if (i != 1) {
                                mplist.add(mp);
                            }
                        }
                        if("classListname".equals(field.getName())){
                            SubFileInfoRequest subFileInfoRequest = new SubFileInfoRequest();
                            //subFileInfoRequest.setFileType(2L);
                            subFileInfoRequest.setFileOriginName(map.get(field.getName()).toString());
                            subFileInfoRequest.setFileFirstBelong(YunHeKey.KECHENG);
                            PageResult<SubFileInfo> subFileInfoPageResult = subFileInfoService.findPage(subFileInfoRequest);
                            if(!subFileInfoPageResult.getRows().isEmpty()) {
                                p.put("fileId", subFileInfoPageResult.getRows().get(0).getId());
                                p.put("fileType", subFileInfoPageResult.getRows().get(0).getFileType());
                            }
                        }

//                        }
                    }
                    i++;
                }
                p.put("list", mplist);
                if (i != 1) {
                    mapList.add(p);
                }
            }
        }
        return mapList;
    }
}